package org.hit.monitor.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.hit.monitor.bo.QueryMetricsBO;
import org.hit.monitor.common.BatchResultDTO;
import org.hit.monitor.common.CONFIG;
import org.hit.monitor.common.Metrics;
import org.hit.monitor.common.ResultDTO;
import org.hit.monitor.model.MetricsDataDO;
import org.hit.monitor.service.MetricsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/index")
public class IndexController extends BaseController {
	
	private Logger log = LoggerFactory.getLogger(getClass());
	
	@Autowired
	MetricsService metricsService;
	
	/**
	 * 获取CPU数据
	 */
	@ResponseBody
	@RequestMapping("/cpu")
	public String fetchCpuData(HttpServletRequest request) {
		Integer limit = 1;
		Long start = null;
		String limitStr = request.getParameter("limit");
		String startStr = request.getParameter("start");
		if (limitStr != null) {
			limit = Integer.parseInt(limitStr);
		}
		if (startStr != null) {
			start = Long.parseLong(startStr);
		}
		QueryMetricsBO filter = new QueryMetricsBO();
		filter.setDesc(true);
		filter.setLimit(limit);
		filter.setStart(start);
		BatchResultDTO<MetricsDataDO> result = metricsService.fetchData(Metrics.CPU.IDLE, filter);
		if (result.isSuccess()) {
			return responseControllerResultSuccess(result.getModule());
		} else {
			return responseControllerResultError(result.getErrorDetail());
		}
	}
	
	/**
	 * 获取集群负载数据
	 */
	@ResponseBody
	@RequestMapping("/load")
	public String fetchClusterLoadData(HttpServletRequest request) {
		Integer limit = 1;
		Long start = null;
		String limitStr = request.getParameter("limit");
		String startStr = request.getParameter("start");
		if (limitStr != null) {
			limit = Integer.parseInt(limitStr);
		}
		if (startStr != null) {
			start = Long.parseLong(startStr);
		}
		QueryMetricsBO filter = new QueryMetricsBO();
		filter.setDesc(true);
		filter.setLimit(limit);
		filter.setStart(start);
		BatchResultDTO<MetricsDataDO> result = metricsService.fetchData(Metrics.LOAD.LOAD_ONE, filter);
		if (result.isSuccess()) {
			return responseControllerResultSuccess(result.getModule());
		} else {
			return responseControllerResultError(result.getErrorDetail());
		}
	}
	
	/**
	 * 获取集群运行应用数据
	 */
	@ResponseBody
	@RequestMapping("/app")
	public String fetchClusterAppData(HttpServletRequest request) {
		try {
			String mapReduceUri = CONFIG.YARN_RESOURCE_MANAGER + "/appstatistics?applicationTypes=mapreduce";
			String sparkUri = CONFIG.SPARK_HISTORY_SERVER + "/applications?status=running";
			
			ResultDTO<String> mapReduceResult = metricsService.fetchMetricsJSONByAPI(mapReduceUri);
			ResultDTO<String> sparkResult = metricsService.fetchMetricsJSONByAPI(sparkUri);
			
			JSONObject jo = new JSONObject();
			jo.put("mapReduceApp", JSON.parseObject(mapReduceResult.getModule()));
			jo.put("sparkApp", JSON.parseArray(sparkResult.getModule()));
			return jo.toJSONString();
		} catch (Exception e) {
			log.error("JSON数据转换异常", e);
			return responseControllerResultError("JSON数据转换异常");
		}
	}
	
	/**
	 * 若干非图表类信息：RPC队列时间、磁盘空闲空间、内存空闲空间
	 */
	@ResponseBody
	@RequestMapping("/mass")
	public String fetchMassiveData(HttpServletRequest request) {
		
		try {
			QueryMetricsBO filter = new QueryMetricsBO();
			filter.setDesc(true);
			filter.setLimit(1); // 只取最新的一条数据
			
			//RPC平均处理时间
			List<MetricsDataDO> rpcProcessTimeAvg = metricsService.fetchData(Metrics.RPC.RPC_PROCESSING_TIME_AVG_TIME, filter).getModule();
			
			//磁盘空闲空间
			List<MetricsDataDO> diskFree = metricsService.fetchData(Metrics.DISK.DISK_FREE, filter).getModule();
			
			//内存空闲空间
			List<MetricsDataDO> memFree = metricsService.fetchData(Metrics.MEMORY.FREE, filter).getModule();
			
			Map<String, Object> result = new HashMap<String, Object>();
			if (CollectionUtils.isNotEmpty(rpcProcessTimeAvg)) {
				result.put("rpc", rpcProcessTimeAvg.get(0));
			}
			if (CollectionUtils.isNotEmpty(diskFree)) {
				result.put("diskFree", diskFree.get(0));
			}
			if (CollectionUtils.isNotEmpty(memFree)) {
				result.put("memFree", memFree.get(0));
			}
			return responseControllerResultSuccess(result);
		} catch (Exception e) {
			log.error("获取首页数据出错", e);
			return responseControllerResultError("参数错误");
		}
	}
	
	/**
	 * 获取一些变化概率很低的信息：总磁盘空间、总内存大小
	 */
	@ResponseBody
	@RequestMapping("/stable")
	public String fetchStableData(HttpServletRequest request) {
		QueryMetricsBO filter = new QueryMetricsBO();
		filter.setDesc(true);
		filter.setLimit(1);
		List<MetricsDataDO> diskTotal = metricsService.fetchData(Metrics.DISK.DISK_TOTAL, filter).getModule();
		List<MetricsDataDO> memTotal = metricsService.fetchData(Metrics.MEMORY.TOTAL, filter).getModule();
		List<MetricsDataDO> cpuNum = metricsService.fetchData(Metrics.CPU.NUM, filter).getModule();
		
		Map<String, Object> result = new HashMap<String, Object>();
		if (CollectionUtils.isNotEmpty(diskTotal)) {
			result.put("diskTotal", diskTotal.get(0));
		}
		if (CollectionUtils.isNotEmpty(memTotal)) {
			result.put("memTotal", memTotal.get(0));
		}
		if (CollectionUtils.isNotEmpty(cpuNum)) {
			result.put("cpuNum", cpuNum.get(0));
		}
		return responseControllerResultSuccess(result);
	}
	
	/**
	 * 通过Mesos接口获取集群总从节点、存活节点等信息
	 */
	@ResponseBody
	@RequestMapping("/cluster/agent")
	public String fetchAgentData(HttpServletRequest request) {
		ResultDTO<String> result = metricsService.fetchMetricsJSONByAPI(CONFIG.MESOS_MASTER + "/metrics/snapshot");
		if (result.isSuccess()) {
			return result.getModule();
		} else {
			return responseControllerResultError(result.getErrorDetail());
		}
	}
	
	/**
	 * 通过ResourceManager接口获取集群总节点、存活节点、运行中的应用等信息
	 */
	@ResponseBody
	@RequestMapping("/cluster/metrics")
	public String fetchClusterMetricsData(HttpServletRequest request) {
		ResultDTO<String> result = metricsService.fetchMetricsJSONByAPI(CONFIG.YARN_RESOURCE_MANAGER + "/metrics");
		if (result.isSuccess()) {
			return result.getModule();
		} else {
			return responseControllerResultError(result.getErrorDetail());
		}
	}
	
	/**
	 * 获得异构资源分配信息
	 */
	@ResponseBody
	@RequestMapping("/cluster/resource")
	public String fetchClusterResourceData(HttpServletRequest request) {
		try {
			ResultDTO<String> mesosFrameworks = metricsService.fetchMetricsJSONByAPI(CONFIG.MESOS_MASTER + "/frameworks");
			ResultDTO<String> marathonApps = metricsService.fetchMetricsJSONByAPI(CONFIG.MARATHON_API + "/v2/apps?label=monitor");
			
			JSONArray result = new JSONArray();
			if (mesosFrameworks.isSuccess() && mesosFrameworks.getModule() != null) {
				JSONArray mesosFrameworksArr = JSON.parseObject(mesosFrameworks.getModule()).getJSONArray("frameworks");
				for (int i = 0; i < mesosFrameworksArr.size(); i++) {
					JSONObject frame = mesosFrameworksArr.getJSONObject(i);
					
					if ("marathon".equals(frame.get("name").toString()) || "false".equals(frame.get("active").toString())) {
						continue;
					}
					JSONObject resource = frame.getJSONObject("used_resources");
					JSONObject jo = new JSONObject();
					jo.put("name", frame.get("name"));
					jo.put("cpus", resource.get("cpus"));
					jo.put("gpus", resource.get("gpus"));
					jo.put("mem", resource.get("mem"));
					jo.put("disk", resource.get("disk"));
					result.add(jo);
				}
			}
			
			if (marathonApps.isSuccess() && marathonApps.getModule() != null) {
				JSONArray marathonAppArr = JSON.parseObject(marathonApps.getModule()).getJSONArray("apps");
				for (int i = 0; i < marathonAppArr.size(); i++) {
					JSONObject app = marathonAppArr.getJSONObject(i);
					if (app.getInteger("instances") == 0) {
						continue;
					}
					JSONObject jo = new JSONObject();
					jo.put("name", app.get("id"));
					jo.put("cpus", app.get("cpus"));
					jo.put("gpus", app.get("gpus"));
					jo.put("mem", app.get("mem"));
					jo.put("disk", app.get("disk"));
					result.add(jo);
				}
			}
			return result.toJSONString();
		} catch (Exception e) {
			log.error("服务器错误", e);
			return responseControllerResultError("服务器错误");
		}
	}
}
